#include<cstdio>//uncle-lu
#include<cstring>
#include<queue>
#include<algorithm>
template<class T>void read(T &x)
{
	x=0;int f=0;char ch=getchar();
	while(ch<'0'||ch>'9') { f|=(ch=='-'); ch=getchar(); }
	while(ch<='9'&&ch>='0') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
	x = f ? -x : x;
	return ;
}

void add_edge(int, int, int);
void spfa(void);

struct node{
	int v, next, val;
};
node edge[300010];
int head[100010], cnt, n, k;
int d[100010];
bool visit[100010];
int count_visit[100010];

void add_edge(int x, int y, int val)
{
	edge[++cnt].v = y;
	edge[cnt].val = val;
	edge[cnt].next = head[x];
	head[x] = cnt;
	return ;
}

void spfa()
{
	memset(d,-0x7f7f7f7f,sizeof(d));
	d[0] = 0;
	visit[0] = true;
	count_visit[0] ++;

	std::queue<int>qu;
	qu.push(0);
	while(!qu.empty())
	{
		int now = qu.front();
		qu.pop();

		visit[now] = false;
		count_visit[now] ++;
		if(count_visit[now] == n)
		{
			printf("-1");
			exit(0);
		}

		for(int i=head[now];~i;i=edge[i].next)
		{
			if(d[edge[i].v] < d[now] + edge[i].val)
			{
				d[edge[i].v] = d[now] + edge[i].val;
				if(!visit[edge[i].v])
				{
					visit[edge[i].v] = true;
					qu.push(edge[i].v);
				}
			}
		}
	}

	return ;
}

int main()
{
	memset(head,-1,sizeof(head));

	int model, x, y;
	read(n);read(k);
	for(int i=1;i<=k;++i)
	{
		read(model); read(x); read(y);
		if(model == 1)
		{
			add_edge(x, y, 0);
			add_edge(y, x, 0);
		}
		else if(model == 2)
		{
			if( x == y )
			{
				printf("-1");
				return 0;
			}
			add_edge(x, y, 1);
		}
		else if(model == 3)
			add_edge(y, x, 0);
		else if(model == 4)
		{
			if( x == y )
			{
				printf("-1");
				return 0;
			}
			add_edge(y, x, 1);
		}
		else if(model == 5)
			add_edge(x, y, 0);
	}

	for(int i=n;i>=1;--i)
		add_edge(0, i, 1);

	spfa();

	long long int ans = 0;
	for(int i=1;i<=n;++i)
		ans += d[i];

	printf("%lld",ans);

	return 0;
}
